home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #4 / Amiga Plus CD - 2000 - No. 4.iso / Tools / Musik / Misc / Amster / Source / transfer.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-27  |  8.5 KB  |  382 lines

  1. /*
  2. ** Transfer
  3. */
  4.  
  5. #include "include/config.h"
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9.  
  10. #include <proto/dos.h>
  11. #include <proto/exec.h>
  12. #include <proto/socket.h>
  13.  
  14. #include <netdb.h>
  15. #include <sys/time.h>
  16. #include <sys/socket.h>
  17. #include <sys/ioctl.h>
  18. #include <netinet/tcp.h>
  19. #include <bsdsocket/socketbasetags.h>
  20. #include <error.h>
  21. #include <time.h>
  22.  
  23. #include "include/mui.h"
  24. #include <MUI/NListview_mcc.h>
  25. #include "include/download.h"
  26. #include "include/upload.h"
  27. #include "include/gui.h"
  28. #include "include/panel.h"
  29. #include "include/prefs.h"
  30. #include "include/transfer.h"
  31. #include "amster_Cat.h"
  32. #include "include/protos.h"
  33.  
  34.  
  35. MUIF translistdisp(REG(a2) char **array, REG(a1) songtrans sd)
  36. {
  37.     static char buf2[50],buf3[50],buf4[50],buf5[50];
  38.  
  39.     static char *states[] = {
  40.         (char *)_MSG_TRANS_STAT_PREPARE,
  41.         (char *)_MSG_TRANS_STAT_QUEUE,
  42.         (char *)_MSG_TRANS_STAT_WAIT,
  43.         (char *)_MSG_TRANS_STAT_CONN,
  44.         (char *)_MSG_TRANS_STAT_REQ,
  45.         (char *)_MSG_TRANS_STAT_INIT,
  46.         (char *)_MSG_TRANS_STAT_DL,
  47.         (char *)_MSG_TRANS_STAT_UL,
  48.         (char *)_MSG_TRANS_STAT_FIN,
  49.         (char *)_MSG_TRANS_STAT_ABORT,
  50.         (char *)_MSG_TRANS_STAT_ERROR,
  51.         NULL
  52.     };
  53.  
  54.     static char *errors[] = {
  55.         (char *)_MSG_TRANS_STAT_ERROR,
  56.         (char *)_MSG_TRANS_ERROR_FILEOPEN,
  57.         (char *)_MSG_TRANS_ERROR_FILEREAD,
  58.         (char *)_MSG_TRANS_ERROR_FILEWRITE,
  59.         (char *)_MSG_TRANS_ERROR_NET_UNKNOWN,
  60.         (char *)_MSG_TRANS_ERROR_LOGGEDOUT,
  61.         (char *)_MSG_TRANS_ERROR_NOTFOUND,
  62.         (char *)_MSG_TRANS_ERROR_INVALIDREQUEST,
  63.         (char *)_MSG_TRANS_ERROR_TEASER,
  64.         (char *)_MSG_TRANS_ERROR_BUSY,
  65.         NULL
  66.     };
  67.  
  68.     static char *NetError[] = {
  69.         (char *)_MSG_TRANS_ERROR_NET_TIMEOUT,
  70.         (char *)_MSG_TRANS_ERROR_NET_REFUSED,
  71.         (char *)_MSG_TRANS_ERROR_NET_RESET,
  72.         (char *)_MSG_TRANS_ERROR_NET_PIPE,
  73.         NULL
  74.     };
  75.  
  76.     if(states[0] == (char *)_MSG_TRANS_STAT_PREPARE)
  77.         localize_array(states);
  78.  
  79.     if(errors[0] == (char *)_MSG_TRANS_STAT_ERROR)
  80.         localize_array(errors);
  81.  
  82.     if(NetError[0] == (char *)_MSG_TRANS_ERROR_NET_TIMEOUT)
  83.         localize_array(NetError);
  84.  
  85.     if(sd) {
  86.         *array++ = nap_strippath(sd->song->title);
  87.  
  88.         if (sd->state == DLS_WAIT) {
  89.             sprintf(buf5, states[sd->state], sd->ErrorCode);
  90.             *array++ = buf5;
  91.         }
  92.         else if (sd->state != DLS_ERROR)
  93.             *array++ = states[sd->state];
  94.         else {
  95.             switch (sd->error) {
  96.                 case ERROR_FILEOPEN:
  97.                 case ERROR_FILEREAD:
  98.                 case ERROR_FILEWRITE:
  99.                     sprintf(buf5, errors[sd->error], sd->ErrorCode);
  100.                     *array++ = buf5;
  101.                     break;
  102.                 case ERROR_NET:
  103.                     switch (sd->ErrorCode) {
  104.                         case ETIMEDOUT:
  105.                             *array++ = NetError[ERROR_NET_TIMEOUT];
  106.                             break;
  107.                         case ECONNREFUSED:
  108.                             *array++ = NetError[ERROR_NET_REFUSED];
  109.                             break;
  110.                         default:
  111.                             sprintf(buf5, errors[sd->error], sd->ErrorCode);
  112.                             *array++ = buf5;
  113.                     }
  114.                     break;
  115.                 default:
  116.                     *array++ = errors[sd->error];
  117.             }
  118.         }
  119.  
  120.         if (sd->size > 0)
  121.             sprintf(buf2,"\33r%ld / %ld (%d%%)", sd->cur, sd->size, (sd->cur*100+5)/sd->size);
  122.         else sprintf(buf2, "\33r0");    /* Can this happen? */
  123.         *array++ = buf2;
  124.  
  125.         if (sd->cps > 0) {
  126.             if (sd->stalltick<5) {    /* 5 seconds */
  127.                 sprintf(buf3,"%d",sd->cps);
  128.                 *array++ = buf3;
  129.             }
  130.             else {
  131.                 *array++ = (char *)MSG_TRANS_STAT_STALLED;
  132.             }
  133.             sprintf(buf4,"%ld:%02ld / %ld:%02ld",sd->transtime/60,sd->transtime%60,sd->timeleft/60,sd->timeleft%60);
  134.             *array = buf4;
  135.         }
  136.         else {
  137.             *array++ = "-";
  138.             *array   = "-";
  139.         }
  140.  
  141.     }
  142.     else {
  143.         *array++ = (char *)MSG_LH_FILE;
  144.         *array++ = (char *)MSG_LH_STATE;
  145.         *array++ = (char *)MSG_LH_SIZE;
  146.         *array++ = (char *)MSG_LH_CPS;
  147.         *array =   (char *)MSG_LH_ETIME;
  148.     }
  149.     return(0);
  150. }
  151.  
  152.  
  153. ULONG dl_setup(struct IClass *cl, Object *obj, Msg msg)
  154. {
  155.     struct TransferData *data = INST_DATA(cl,obj);
  156.  
  157.     if (!DoSuperMethodA(cl,obj,msg))
  158.         return(FALSE);
  159.  
  160.     DoMethod(_app(obj), MUIM_Application_AddInputHandler, &data->ihnode);
  161.  
  162.     return(TRUE);
  163. }
  164.  
  165.  
  166. ULONG dl_muicleanup(struct IClass *cl, Object *obj, Msg msg)
  167. {
  168.     struct TransferData *data = INST_DATA(cl,obj);
  169.  
  170.     DoMethod(_app(obj), MUIM_Application_RemInputHandler, &data->ihnode);
  171.  
  172.     return(DoSuperMethodA(cl,obj,msg));
  173. }
  174.  
  175.  
  176. void CalculateCps(songtrans sd)
  177. {
  178.     if (sd->cur != sd->oldsize) {
  179.         sd->stalltick = 0;
  180.         sd->oldsize = sd->cur;
  181.     }
  182.     else sd->stalltick++;
  183.  
  184.     sd->transtime = time(NULL) - sd->starttime;
  185.     if (sd->transtime == 0) sd->transtime = 1;
  186.     sd->cps = (sd->cur - sd->resumestart) / sd->transtime;
  187.     if (sd->cps > 0)
  188.         sd->timeleft = (sd->size - sd->cur) / sd->cps;
  189.     else sd->timeleft = 0;
  190. }
  191.  
  192.  
  193. void TransferSetError(struct TransferData *data, char *title, char *user, int error)
  194. {
  195.     u_long tmp;
  196.     songtrans sd;
  197.     long i;
  198.  
  199.     for (i=0; ; i++) {
  200.         DoMethod(data->list, MUIM_NList_GetEntry, i, &tmp);
  201.         if (!tmp) return;
  202.         sd = (songtrans)tmp;
  203.         if (strcmp(sd->song->title, title) == 0 && stricmp(sd->song->user, user) == 0) break;
  204.     }
  205.  
  206.     sd->state = DLS_ERROR;
  207.     sd->error = error;
  208.  
  209.     if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) DoMethod(gui->dwin, DL_UPDATE, sd);
  210.     else DoMethod(gui->uwin, UPLOAD_UPDATE, sd);
  211. }
  212.  
  213.  
  214. void TransferInfo(struct TransferData *data)
  215. {
  216.     static char buf[600];
  217.     u_long tmp;
  218.     songtrans sd;
  219.  
  220.     GetAttr(MUIA_NList_EntryClick,  data->list, &tmp);
  221.     if (tmp == -1 || tmp == -2) return;
  222.     DoMethod(data->list, MUIM_NList_GetEntry, tmp, &sd);
  223.     if (!sd) return;
  224.  
  225.     if(sd->host[0] == '\0') {
  226.         sprintf(buf, "%s (%s)", sd->song->user, Inet_NtoA(sd->song->ip));
  227.     }
  228.     else {
  229.         sprintf(buf, "%s (%s)", sd->song->user, sd->host);
  230.     }
  231.  
  232.     set(data->info, MUIA_Text_Contents, buf);
  233. }
  234.  
  235.  
  236. void TransferCleanup(struct TransferData *data)
  237. {
  238.     u_long item;
  239.     int i=0, j;
  240.  
  241.     while (1) {
  242.         DoMethod(data->list, MUIM_NList_GetEntry, i, &item);
  243.         if (!item) break;
  244.         j = ((songtrans)item)->state;
  245.         if (j >= DLS_FIN) {
  246.             DoMethod(data->list,MUIM_NList_Remove,i);
  247.             nap_songfree(((songtrans)item)->song);
  248.             if (((songtrans)item)->fname) free(((songtrans)item)->fname);
  249.             free((songtrans)item);
  250.         } else i++;
  251.     }
  252. }
  253.  
  254.  
  255. void TransferHandleError(songtrans sd)
  256. {
  257.     char error[128];
  258.  
  259.     if (sd->error != 0) {
  260.         sd->state = DLS_ERROR;
  261.         if (sd->error >= ERROR_FILEOPEN && sd->error <= ERROR_FILEWRITE) {
  262.             Fault(sd->ErrorCode, "", error, 127);
  263.             gui_debugf((char *)MSG_INFO_IOERROR, sd->fname, error);
  264.         }
  265.         else if (sd->error >= ERROR_OUTOFBOUND) sd->error = ERROR_UNKNOWN;
  266.         prf_event(PRFE_DLERROR);
  267.     }
  268.     else if (sd->state == DLS_FIN) {
  269.         if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) prf_event(PRFE_DLFINISH);
  270.         else prf_event(PRFE_ULFINISH);
  271.     }
  272.  
  273.     if (sd->type == TYPE_DOWNLOAD_OUT || sd->type == TYPE_DOWNLOAD_IN) DoMethod(gui->dwin, DL_UPDATE, sd);
  274.     else DoMethod(gui->uwin, UPLOAD_UPDATE, sd);
  275. }
  276.  
  277.  
  278. /* Thread stuff */
  279.  
  280. BOOL InitTransferThread(thread t, songtrans sd)
  281. {
  282.     struct Library *DosBase;
  283.     struct Library *SocketBase;
  284.     char *buffer;
  285.     long s;
  286.     long tmp;
  287.     struct hostent *he;
  288.  
  289.     sd->state = DLS_PREP;
  290.  
  291.     sd->nsig = AllocSignal(-1);
  292.     if (sd->nsig == -1) {
  293.         ExitTransferThread(sd, 1);
  294.         return FALSE;
  295.     }
  296.     sd->nsigm = (1L << (sd->nsig));
  297.     sd->msigm = (1L << (t->port->mp_SigBit));
  298.  
  299.     DosBase = OpenLibrary("dos.library", 0);
  300.     if (!DosBase) {
  301.         ExitTransferThread(sd, 1);
  302.         return FALSE;
  303.     }
  304.     sd->DosBase = DosBase;
  305.  
  306.     SocketBase = OpenLibrary("bsdsocket.library", 0);
  307.     if (!SocketBase) {
  308.         ExitTransferThread(sd, 1);
  309.         return FALSE;
  310.     }
  311.     sd->SocketBase = SocketBase;
  312.     SocketBaseTags(SBTM_SETVAL(SBTC_SIGIOMASK), (char *)sd->nsigm, TAG_DONE);
  313.  
  314.     buffer = malloc(8192);
  315.     if (!buffer) {
  316.         ExitTransferThread(sd, 2);
  317.         return FALSE;
  318.     }
  319.     sd->buffer = buffer;
  320.  
  321.     /* Perform DNS-lookup */
  322.     he = gethostbyname(Inet_NtoA(sd->song->ip));
  323.     he = gethostbyaddr(he->h_addr_list[0], he->h_length, AF_INET);
  324.     if (he != 0) strcpy(sd->host, he->h_name);
  325.     else strcpy(sd->host, Inet_NtoA(sd->song->ip));
  326.  
  327.     s = socket(AF_INET, SOCK_STREAM, 0);
  328.     if (s<0) {
  329.         ExitTransferThread(sd, 3);
  330.         return FALSE;
  331.     }
  332.     sd->s = s;
  333.  
  334.     sd->sin.sin_addr.s_addr = sd->ip;
  335.     sd->sin.sin_port = sd->port;
  336.     sd->sin.sin_family = AF_INET;
  337.     sd->sin.sin_len = sizeof(sd->sin);
  338.  
  339.     tmp = 1;
  340.     IoctlSocket(s, FIOASYNC, (char *)&tmp);
  341.     IoctlSocket(s, FIONBIO,  (char *)&tmp);
  342.     /* Asynchronous and non-blocking I/O to the socket */
  343.  
  344.     tmp = connect(s, (struct sockaddr *)&sd->sin, sizeof(sd->sin));
  345.     if (tmp == -1 && Errno() != EINPROGRESS) {
  346.         sd->ErrorCode = Errno();
  347.         ExitTransferThread(sd, ERROR_NET);
  348.         return FALSE;
  349.     }
  350.  
  351.     thr_message(t, DLC_STATE, (APTR)DLS_CON);
  352.  
  353.     return TRUE;
  354. }
  355.  
  356.  
  357. void ExitTransferThread(songtrans sd, int ret)
  358. {
  359.     struct Library *DosBase=sd->DosBase;
  360.     struct Library *SocketBase=sd->SocketBase;
  361.  
  362.     if (sd->nsig != -1) FreeSignal(sd->nsig);
  363.     sd->nsig = -1;
  364.  
  365.     if (sd->f) Close(sd->f);
  366.     sd->f = 0;
  367.  
  368.     if (sd->s != -1) CloseSocket(sd->s);
  369.     sd->s = -1;
  370.  
  371.     if (sd->buffer) free(sd->buffer);
  372.     sd->buffer = NULL;
  373.  
  374.     if (SocketBase) CloseLibrary(SocketBase);
  375.     sd->SocketBase = NULL;
  376.  
  377.     if (DosBase) CloseLibrary(DosBase);
  378.     sd->DosBase = NULL;
  379.  
  380.     thr_exit(sd->t, ret);
  381. }
  382.